home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / tcsh / Source / ed.inputl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  16.2 KB  |  680 lines

  1. /* $Header: /u/christos/src/tcsh-6.03/RCS/ed.inputl.c,v 3.31 1992/11/13 04:19:10 christos Exp $ */
  2. /*
  3.  * ed.inputl.c: Input line handling.
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: ed.inputl.c,v 3.31 1992/11/13 04:19:10 christos Exp $")
  40.  
  41. #include "ed.h"
  42. #include "ed.defns.h"        /* for the function names */
  43. #include "tw.h"            /* for twenex stuff */
  44.  
  45. #define OKCMD (INBUFSIZE+INBUFSIZE)
  46. extern CCRETVAL e_up_hist();
  47. extern CCRETVAL e_expand_history();
  48.  
  49. /* ed.inputl -- routines to get a single line from the input. */
  50.  
  51. extern bool tellwhat;
  52. extern bool MapsAreInited;
  53. extern bool Tty_raw_mode;
  54.  
  55. /* mismatched first character */
  56. static Char mismatch[] = {'!', '\\', '^', '-', '%', '\0'};
  57.  
  58. static    int    GetNextCommand    __P((KEYCMD *, Char *));
  59. static    int    SpellLine    __P((int));
  60. static    void    RunCommand    __P((Char *));
  61. static void     doeval1        __P((Char **));
  62.  
  63. /* CCRETVAL */
  64. int
  65. Inputl()
  66. {
  67.     CCRETVAL retval;
  68.     KEYCMD  cmdnum = 0;
  69.     extern KEYCMD NumFuns;
  70.     unsigned char tch;        /* the place where read() goes */
  71.     Char    ch;
  72.     int     num;        /* how many chars we have read at NL */
  73.     int        expnum;
  74.     struct varent *crct = adrof(STRcorrect);
  75.     struct varent *autol = adrof(STRautolist);
  76.     struct varent *matchbeep = adrof(STRmatchbeep);
  77.     struct varent *imode = adrof(STRinputmode);
  78.     Char   *SaveChar, *CorrChar;
  79.     Char    Origin[INBUFSIZE], Change[INBUFSIZE];
  80.     int     matchval;        /* from tenematch() */
  81.     COMMAND fn;
  82.  
  83.     if (!MapsAreInited)        /* double extra just in case */
  84.     ed_InitMaps();
  85.  
  86.     ClearDisp();        /* reset the display stuff */
  87.     ResetInLine(0);        /* reset the input pointers */
  88.     if (GettingInput)
  89.     MacroLvl = -1;        /* editor was interrupted during input */
  90.  
  91.     if (imode) {
  92.     if (!Strcmp(*(imode->vec), STRinsert))
  93.         inputmode = MODE_INSERT;
  94.     else if (!Strcmp(*(imode->vec), STRoverwrite))
  95.         inputmode = MODE_REPLACE;
  96.     }
  97.  
  98. #if defined(FIONREAD) && !defined(OREO)
  99.     if (!Tty_raw_mode && MacroLvl < 0) {
  100.     long    chrs = 0;
  101.  
  102.     (void) ioctl(SHIN, FIONREAD, (ioctl_t) & chrs);
  103.     if (chrs == 0) {
  104.         if (Rawmode() < 0)
  105.         return 0;
  106.     }
  107.     }
  108. #endif /* FIONREAD && !OREO */
  109.  
  110.     GettingInput = 1;
  111.     NeedsRedraw = 0;
  112.  
  113.     if (tellwhat) {
  114.     copyn(InputBuf, WhichBuf, INBUFSIZE);
  115.     LastChar = InputBuf + (LastWhich - WhichBuf);
  116.     Cursor = InputBuf + (CursWhich - WhichBuf);
  117.     tellwhat = 0;
  118.     Hist_num = HistWhich;
  119.     }
  120.     if (Expand) {
  121.     (void) e_up_hist(0);
  122.     Expand = 0;
  123.     }
  124.     Refresh();            /* print the prompt */
  125.  
  126.     for (num = OKCMD; num == OKCMD;) {    /* while still editing this line */
  127. #ifdef DEBUG_EDIT
  128.     if (Cursor > LastChar)
  129.         xprintf("Cursor > LastChar\r\n");
  130.     if (Cursor < InputBuf)
  131.         xprintf("Cursor < InputBuf\r\n");
  132.     if (Cursor > InputLim)
  133.         xprintf("Cursor > InputLim\r\n");
  134.     if (LastChar > InputLim)
  135.         xprintf("LastChar > InputLim\r\n");
  136.     if (InputLim != &InputBuf[INBUFSIZE - 2])
  137.         xprintf("InputLim != &InputBuf[INBUFSIZE-2]\r\n");
  138.     if ((!DoingArg) && (Argument != 1))
  139.         xprintf("(!DoingArg) && (Argument != 1)\r\n");
  140.     if (CcKeyMap[0] == 0)
  141.         xprintf("CcKeyMap[0] == 0 (maybe not inited)\r\n");
  142. #endif
  143.  
  144.     /* if EOF or error */
  145.     if ((num = GetNextCommand(&cmdnum, &ch)) != OKCMD) {
  146.         break;
  147.     }
  148.  
  149.     if (cmdnum >= NumFuns) {/* BUG CHECK command */
  150. #ifdef DEBUG_EDIT
  151.         xprintf("ERROR: illegal command from key 0%o\r\n", ch);
  152. #endif
  153.         continue;        /* try again */
  154.     }
  155.  
  156.     /* now do the real command */
  157.     retval = (*CcFuncTbl[cmdnum]) (ch);
  158.  
  159.     /* save the last command here */
  160.     LastCmd = cmdnum;
  161.  
  162.     /* use any return value */
  163.     switch (retval) {
  164.  
  165.     case CC_REFRESH:
  166.         Refresh();
  167.         /*FALLTHROUGH*/
  168.     case CC_NORM:        /* normal char */
  169.         Argument = 1;
  170.         DoingArg = 0;
  171.         /*FALLTHROUGH*/
  172.     case CC_ARGHACK:    /* Suggested by Rich Salz */
  173.         /* <rsalz@pineapple.bbn.com> */
  174.         break;        /* keep going... */
  175.  
  176.     case CC_EOF:        /* end of file typed */
  177.         num = 0;
  178.         break;
  179.  
  180.     case CC_WHICH:        /* tell what this command does */
  181.         tellwhat = 1;
  182.         copyn(WhichBuf, InputBuf, INBUFSIZE);
  183.         LastWhich = WhichBuf + (LastChar - InputBuf);
  184.         CursWhich = WhichBuf + (Cursor - InputBuf);
  185.         *LastChar++ = '\n';    /* for the benifit of CSH */
  186.         HistWhich = Hist_num;
  187.         Hist_num = 0;    /* for the history commands */
  188.         num = LastChar - InputBuf;    /* number characters read */
  189.         break;
  190.  
  191.     case CC_NEWLINE:    /* normal end of line */
  192.         if (crct && (!Strcmp(*(crct->vec), STRcmd) ||
  193.              !Strcmp(*(crct->vec), STRall))) {
  194.         copyn(Origin, InputBuf, INBUFSIZE);
  195.         SaveChar = LastChar;
  196.         if (SpellLine(!Strcmp(*(crct->vec), STRcmd)) == 1) {
  197.             copyn(Change, InputBuf, INBUFSIZE);
  198.             *Strchr(Change, '\n') = '\0';
  199.             CorrChar = LastChar;    /* Save the corrected end */
  200.             LastChar = InputBuf;    /* Null the current line */
  201.             Beep();
  202.             printprompt(2, short2str(Change));
  203.             Refresh();
  204.             (void) read(SHIN, (char *) &tch, 1);
  205.             ch = tch;
  206.             if (ch == 'y' || ch == ' ') {
  207.             LastChar = CorrChar;    /* Restore the corrected end */
  208.             xprintf("yes\n");
  209.             }
  210.             else {
  211.             copyn(InputBuf, Origin, INBUFSIZE);
  212.             LastChar = SaveChar;
  213.             if (ch == 'e') {
  214.                 xprintf("edit\n");
  215.                 *LastChar-- = '\0';
  216.                 Cursor = LastChar;
  217.                 printprompt(3, NULL);
  218.                 Refresh();
  219.                 break;
  220.             }
  221.             else if (ch == 'a') {
  222.                 xprintf("abort\n");
  223.                 *LastChar = '\0';
  224.                 Cursor = LastChar;
  225.                 printprompt(0, NULL);
  226.                 Refresh();
  227.                 break;
  228.             }
  229.             xprintf("no\n");
  230.             }
  231.             flush();
  232.         }
  233.         }            /* end CORRECT code */
  234.         tellwhat = 0;    /* just in case */
  235.         Hist_num = 0;    /* for the history commands */
  236.         num = LastChar - InputBuf;    /* return the number of chars read */
  237.         /*
  238.          * For continuation lines, we set the prompt to prompt 2
  239.          */
  240.         printprompt(1, NULL);
  241.         break;
  242.  
  243.     case CC_CORRECT:
  244.         if (tenematch(InputBuf, Cursor - InputBuf, SPELL) < 0)
  245.         Beep();        /* Beep = No match/ambiguous */
  246.         if (NeedsRedraw) {
  247.         ClearLines();
  248.         ClearDisp();
  249.         NeedsRedraw = 0;
  250.         }
  251.         Refresh();
  252.         Argument = 1;
  253.         DoingArg = 0;
  254.         break;
  255.  
  256.     case CC_CORRECT_L:
  257.         if (SpellLine(FALSE) < 0)
  258.         Beep();        /* Beep = No match/ambiguous */
  259.         if (NeedsRedraw) {
  260.         ClearLines();
  261.         ClearDisp();
  262.         NeedsRedraw = 0;
  263.         }
  264.         Refresh();
  265.         Argument = 1;
  266.         DoingArg = 0;
  267.         break;
  268.  
  269.  
  270.     case CC_COMPLETE:
  271.     case CC_COMPLETE_ALL:
  272.         fn = (retval == CC_COMPLETE_ALL) ? RECOGNIZE_ALL : RECOGNIZE;
  273.         if (adrof(STRautoexpand))
  274.         (void) e_expand_history(0);
  275.         /*
  276.          * Modified by Martin Boyer (gamin@ireq-robot.hydro.qc.ca):
  277.          * A separate variable now controls beeping after
  278.          * completion, independently of autolisting.
  279.          */
  280.         expnum = Cursor - InputBuf;
  281.         switch (matchval = tenematch(InputBuf, Cursor-InputBuf, fn)){
  282.         case 1:
  283.         if (non_unique_match && matchbeep &&
  284.             (Strcmp(*(matchbeep->vec), STRnotunique) == 0))
  285.             Beep();
  286.         break;
  287.         case 0:
  288.         if (matchbeep) {
  289.             if (Strcmp(*(matchbeep->vec), STRnomatch) == 0 ||
  290.             Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
  291.             Strcmp(*(matchbeep->vec), STRnotunique) == 0)
  292.             Beep();
  293.         }
  294.         else
  295.             Beep();
  296.         break;
  297.         default:
  298.         if (matchval < 0) {    /* Error from tenematch */
  299.             Beep();
  300.             break;
  301.         }
  302.         if (matchbeep) {
  303.             if ((Strcmp(*(matchbeep->vec), STRambiguous) == 0 ||
  304.              Strcmp(*(matchbeep->vec), STRnotunique) == 0))
  305.             Beep();
  306.         }
  307.         else
  308.             Beep();
  309.         /*
  310.          * Addition by David C Lawrence <tale@pawl.rpi.edu>: If an 
  311.          * attempted completion is ambiguous, list the choices.  
  312.          * (PWP: this is the best feature addition to tcsh I have 
  313.          * seen in many months.)
  314.          */
  315.         if (autol && (Strcmp(*(autol->vec), STRambiguous) != 0 || 
  316.                      expnum == Cursor - InputBuf)) {
  317.             PastBottom();
  318.             fn = (retval == CC_COMPLETE_ALL) ? LIST_ALL : LIST;
  319.             (void) tenematch(InputBuf, Cursor-InputBuf, fn);
  320.         }
  321.         break;
  322.         }
  323.         if (NeedsRedraw) {
  324.         PastBottom();
  325.         ClearLines();
  326.         ClearDisp();
  327.         NeedsRedraw = 0;
  328.         }
  329.         Refresh();
  330.         Argument = 1;
  331.         DoingArg = 0;
  332.         break;
  333.  
  334.     case CC_LIST_CHOICES:
  335.     case CC_LIST_ALL:
  336.         fn = (retval == CC_LIST_ALL) ? LIST_ALL : LIST;
  337.         /* should catch ^C here... */
  338.         if (tenematch(InputBuf, Cursor - InputBuf, fn) < 0)
  339.         Beep();
  340.         Refresh();
  341.         Argument = 1;
  342.         DoingArg = 0;
  343.         break;
  344.  
  345.  
  346.     case CC_LIST_GLOB:
  347.         if (tenematch(InputBuf, Cursor - InputBuf, GLOB) < 0)
  348.         Beep();
  349.         Refresh();
  350.         Argument = 1;
  351.         DoingArg = 0;
  352.         break;
  353.  
  354.     case CC_EXPAND_GLOB:
  355.         if (tenematch(InputBuf, Cursor - InputBuf, GLOB_EXPAND) <= 0)
  356.         Beep();        /* Beep = No match */
  357.         if (NeedsRedraw) {
  358.         ClearLines();
  359.         ClearDisp();
  360.         NeedsRedraw = 0;
  361.         }
  362.         Refresh();
  363.         Argument = 1;
  364.         DoingArg = 0;
  365.         break;
  366.  
  367.     case CC_NORMALIZE_PATH:
  368.         if (tenematch(InputBuf, Cursor - InputBuf, PATH_NORMALIZE) <= 0)
  369.         Beep();        /* Beep = No match */
  370.         if (NeedsRedraw) {
  371.         ClearLines();
  372.         ClearDisp();
  373.         NeedsRedraw = 0;
  374.         }
  375.         Refresh();
  376.         Argument = 1;
  377.         DoingArg = 0;
  378.         break;
  379.  
  380.     case CC_EXPAND_VARS:
  381.         if (tenematch(InputBuf, Cursor - InputBuf, VARS_EXPAND) <= 0)
  382.         Beep();        /* Beep = No match */
  383.         if (NeedsRedraw) {
  384.         ClearLines();
  385.         ClearDisp();
  386.         NeedsRedraw = 0;
  387.         }
  388.         Refresh();
  389.         Argument = 1;
  390.         DoingArg = 0;
  391.         break;
  392.  
  393.     case CC_HELPME:
  394.         xputchar('\n');
  395.         /* should catch ^C here... */
  396.         (void) tenematch(InputBuf, LastChar - InputBuf, PRINT_HELP);
  397.         Refresh();
  398.         Argument = 1;
  399.         DoingArg = 0;
  400.         break;
  401.  
  402.     case CC_FATAL:        /* fatal error, reset to known state */
  403. #ifdef DEBUG_EDIT
  404.         xprintf("*** editor fatal ERROR ***\r\n\n");
  405. #endif                /* DEBUG_EDIT */
  406.         /* put (real) cursor in a known place */
  407.         ClearDisp();    /* reset the display stuff */
  408.         ResetInLine(1);    /* reset the input pointers */
  409.         Refresh();        /* print the prompt again */
  410.         Argument = 1;
  411.         DoingArg = 0;
  412.         break;
  413.  
  414.     case CC_ERROR:
  415.     default:        /* functions we don't know about */
  416.         DoingArg = 0;
  417.         Argument = 1;
  418.         Beep();
  419.         flush();
  420.         break;
  421.     }
  422.     }
  423.     (void) Cookedmode();    /* make sure the tty is set up correctly */
  424.     GettingInput = 0;
  425.     flush();            /* flush any buffered output */
  426.     return num;
  427. }
  428.  
  429. void
  430. PushMacro(str)
  431.     Char   *str;
  432. {
  433.     if (str != NULL && MacroLvl + 1 < MAXMACROLEVELS) {
  434.     MacroLvl++;
  435.     KeyMacro[MacroLvl] = str;
  436.     }
  437.     else {
  438.     Beep();
  439.     flush();
  440.     }
  441. }
  442.  
  443. /*
  444.  * Like eval, only using the current file descriptors
  445.  */
  446. static Char **gv = NULL, **gav = NULL;
  447.  
  448. static void
  449. doeval1(v)
  450.     Char **v;
  451. {
  452.     Char  **oevalvec;
  453.     Char   *oevalp;
  454.     int     my_reenter;
  455.     Char  **savegv;
  456.     jmp_buf_t osetexit;
  457.  
  458.     oevalvec = evalvec;
  459.     oevalp = evalp;
  460.     savegv = gv;
  461.     gav = v;
  462.  
  463.  
  464.     gflag = 0, tglob(gav);
  465.     if (gflag) {
  466.     gv = gav = globall(gav);
  467.     gargv = 0;
  468.     if (gav == 0)
  469.         stderror(ERR_NOMATCH);
  470.     gav = copyblk(gav);
  471.     }
  472.     else {
  473.     gv = NULL;
  474.     gav = copyblk(gav);
  475.     trim(gav);
  476.     }
  477.  
  478.     getexit(osetexit);
  479.  
  480.     /* PWP: setjmp/longjmp bugfix for optimizing compilers */
  481. #ifdef cray
  482.     my_reenter = 1;             /* assume non-zero return val */
  483.     if (setexit() == 0) {
  484.         my_reenter = 0;         /* Oh well, we were wrong */
  485. #else /* !cray */
  486.     if ((my_reenter = setexit()) == 0) {
  487. #endif /* cray */
  488.     evalvec = gav;
  489.     evalp = 0;
  490.     process(0);
  491.     }
  492.  
  493.     evalvec = oevalvec;
  494.     evalp = oevalp;
  495.     doneinp = 0;
  496.  
  497.     if (gv)
  498.     blkfree(gv);
  499.  
  500.     gv = savegv;
  501.     resexit(osetexit);
  502.     if (my_reenter)
  503.     stderror(ERR_SILENT);
  504. }
  505.  
  506. static void
  507. RunCommand(str)
  508.     Char *str;
  509. {
  510.     Char *cmd[2];
  511.  
  512.     xputchar('\n');    /* Start on a clean line */
  513.  
  514.     cmd[0] = str;
  515.     cmd[1] = NULL;
  516.  
  517.     (void) Cookedmode();
  518.     GettingInput = 0;
  519.  
  520.     doeval1(cmd);
  521.     
  522.     (void) Rawmode();
  523.     GettingInput = 1;
  524.  
  525.     ClearLines();
  526.     ClearDisp();
  527.     NeedsRedraw = 0;
  528.     Refresh();
  529. }
  530.  
  531. static int
  532. GetNextCommand(cmdnum, ch)
  533.     KEYCMD *cmdnum;
  534.     register Char *ch;
  535. {
  536.     KEYCMD  cmd = 0;
  537.     int     num;
  538.  
  539.     while (cmd == 0 || cmd == F_XKEY) {
  540.     if ((num = GetNextChar(ch)) != 1) {    /* if EOF or error */
  541.         return num;
  542.     }
  543. #ifdef    KANJI
  544.     if (!adrof(STRnokanji) && (*ch & META)) {
  545.         MetaNext = 0;
  546.         cmd = F_INSERT;
  547.         break;
  548.     }
  549.     else
  550. #endif /* KANJI */
  551.     if (MetaNext) {
  552.         MetaNext = 0;
  553.         *ch |= META;
  554.     }
  555.     cmd = CurrentKeyMap[(unsigned char) *ch];
  556.     if (cmd == F_XKEY) {
  557.         XmapVal val;
  558.         switch (GetXkey(ch, &val)) {
  559.         case XK_CMD:
  560.         cmd = val.cmd;
  561.         break;
  562.         case XK_STR:
  563.         PushMacro(val.str);
  564.         break;
  565.         case XK_EXE:
  566.         RunCommand(val.str);
  567.         break;
  568.         default:
  569.         abort();
  570.         break;
  571.         }
  572.     }
  573.     if (!AltKeyMap) 
  574.         CurrentKeyMap = CcKeyMap;
  575.     }
  576.     *cmdnum = cmd;
  577.     return OKCMD;
  578. }
  579.  
  580. int
  581. GetNextChar(cp)
  582.     register Char *cp;
  583. {
  584.     register int num_read;
  585.     int     tried = 0;
  586.     unsigned char tcp;
  587.  
  588.     for (;;) {
  589.     if (MacroLvl < 0) {
  590.         if (!Load_input_line())
  591.         break;
  592.     }
  593.     if (*KeyMacro[MacroLvl] == 0) {
  594.         MacroLvl--;
  595.         continue;
  596.     }
  597.     *cp = *KeyMacro[MacroLvl]++ & CHAR;
  598.     if (*KeyMacro[MacroLvl] == 0) {    /* Needed for QuoteMode On */
  599.         MacroLvl--;
  600.     }
  601.     return (1);
  602.     }
  603.  
  604.     if (Rawmode() < 0)        /* make sure the tty is set up correctly */
  605.     return 0;        /* oops: SHIN was closed */
  606.  
  607.     while ((num_read = read(SHIN, (char *) &tcp, 1)) == -1) {
  608.     if (errno == EINTR)
  609.         continue;
  610.     if (!tried && fixio(SHIN, errno) != -1)
  611.         tried = 1;
  612.     else {
  613.         *cp = '\0';
  614.         return -1;
  615.     }
  616.     }
  617.     *cp = tcp;
  618.     return num_read;
  619. }
  620.  
  621. /*
  622.  * SpellLine - do spelling correction on the entire command line
  623.  * (which may have trailing newline).
  624.  * If cmdonly is set, only check spelling of command words.
  625.  * Return value:
  626.  * -1: Something was incorrectible, and nothing was corrected
  627.  *  0: Everything was correct
  628.  *  1: Something was corrected
  629.  */
  630. static int
  631. SpellLine(cmdonly)
  632.     int     cmdonly;
  633. {
  634.     int     endflag, matchval;
  635.     Char   *argptr, *OldCursor, *OldLastChar;
  636.  
  637.     OldLastChar = LastChar;
  638.     OldCursor = Cursor;
  639.     argptr = InputBuf;
  640.     endflag = 1;
  641.     matchval = 0;
  642.     do {
  643.     while (ismetahash(*argptr) || iscmdmeta(*argptr))
  644.         argptr++;
  645.     for (Cursor = argptr;
  646.          *Cursor != '\0' && ((Cursor != argptr && Cursor[-1] == '\\') ||
  647.                  (!ismetahash(*Cursor) && !iscmdmeta(*Cursor)));
  648.          Cursor++)
  649.          continue;
  650.     if (*Cursor == '\0') {
  651.         Cursor = LastChar;
  652.         if (LastChar[-1] == '\n')
  653.         Cursor--;
  654.         endflag = 0;
  655.     }
  656.     if (!Strchr(mismatch, *argptr) &&
  657.         (!cmdonly || starting_a_command(argptr, InputBuf))) {
  658.         switch (tenematch(InputBuf, Cursor - InputBuf, SPELL)) {
  659.         case 1:        /* corrected */
  660.         matchval = 1;
  661.         break;
  662.         case -1:        /* couldn't be corrected */
  663.         if (!matchval)
  664.             matchval = -1;
  665.         break;
  666.         default:        /* was correct */
  667.         break;
  668.         }
  669.         if (LastChar != OldLastChar) {
  670.         if (argptr < OldCursor)
  671.             OldCursor += (LastChar - OldLastChar);
  672.         OldLastChar = LastChar;
  673.         }
  674.     }
  675.     argptr = Cursor;
  676.     } while (endflag);
  677.     Cursor = OldCursor;
  678.     return matchval;
  679. }
  680.